package slidingWindow;

import java.util.HashMap;

/**
 * 字符串的排列
 * 给你两个字符串s1和s2 ，写一个函数来判断 s2 是否包含 s1的排列。如果是，返回 true ；否则，返回 false 。
 * 换句话说，s1 的排列之一是 s2 的 子串 。
 *
 * 限制
 * 1 <= s1.length, s2.length <= 104
 * s1 和 s2 仅包含小写字母
 */
public class PermutationInString_567 {
    public boolean checkInclusion(String s1, String s2) {
        if (s1.length() > s2.length()) {
            return false;
        }

        HashMap<Character, Integer> target = new HashMap<>();
        for (int i = 0; i < s1.length(); i++) {
            target.put(s1.charAt(i), target.getOrDefault(s1.charAt(i), 0) + 1);
        }

        // 记录完全符合条件的字符个数
        int valid = 0;
        // 记录当前窗口符合条件的字符个数
        HashMap<Character, Integer> window = new HashMap<>();
        // 2个指针都从左到右开始遍历
        int left = 0;
        int right = 0;
        while (right < s2.length()) {
            // 右指针先移动，此时的窗口只会增加不会减少
            char c = s2.charAt(right);
            right++;
            if (target.containsKey(c)) {
                window.put(c, window.getOrDefault(c, 0) + 1);
                if (window.get(c).equals(target.get(c))) {
                    valid++;
                }
            }

            // 窗口缩小的时机，由于是判断子串，所以长度必然相同，当right - left >= s1.length()就可以缩小窗口
            while (right - left >= s1.length()) {
                if (valid == target.size()) {
                    return true;
                }
                char d = s2.charAt(left);
                left++;
                if (target.containsKey(d)) {
                    if (target.get(d).equals(window.get(d))) {
                        valid--;
                    }
                    window.put(d, window.get(d) - 1);
                }
            }
        }

        return false;
    }
}
